package q1.project.modules.system.dept.service;

import java.util.*;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import q1.project.core.exception.BusinessException;
import q1.project.modules.system.dept.dao.DeptDao;
import q1.project.modules.system.dept.entity.DeptEntity;
import q1.project.modules.system.dept.model.DeptCreateVm;
import q1.project.modules.system.dept.model.DeptQueryVm;
import q1.project.modules.system.dept.model.DeptUpdateVm;

/**
 * 部门业务服务
 *
 * @author Q1 Team
 * @version 1.0
 */
@Service
@RequiredArgsConstructor
@Transactional
public class DeptService {

  private final DeptDao deptDao;

  public DeptEntity create(DeptCreateVm.Query query) {
    checkDeptCodeUnique(query.getDeptCode(), null);
    if (query.getParentId() != null) {
      checkParentIdValid(query.getParentId());
    }

    DeptEntity dept = new DeptEntity();
    dept.setDeptCode(query.getDeptCode());
    dept.setDeptName(query.getDeptName());
    dept.setParentId(query.getParentId());
    dept.setLeaderId(query.getLeaderId());
    dept.setDescription(query.getDescription());
    dept.setSortOrder(query.getSortOrder() != null ? query.getSortOrder() : 0);
    dept.setStatus(1);
    dept.setPhone(query.getPhone());
    dept.setEmail(query.getEmail());
    dept.setAddress(query.getAddress());

    return deptDao.save(dept);
  }

  public void update(String id, DeptUpdateVm.Query query) {
    DeptEntity dept = deptDao.findById(id).orElseThrow(() -> new BusinessException("部门不存在"));

    if (query.getDeptCode() != null && !query.getDeptCode().equals(dept.getDeptCode())) {
      checkDeptCodeUnique(query.getDeptCode(), id);
      dept.setDeptCode(query.getDeptCode());
    }

    if (query.getParentId() != null && !query.getParentId().equals(dept.getParentId())) {
      checkParentIdValid(query.getParentId());
      dept.setParentId(query.getParentId());
    }

    if (query.getDeptName() != null) {
      dept.setDeptName(query.getDeptName());
    }
    if (query.getLeaderId() != null) {
      dept.setLeaderId(query.getLeaderId());
    }
    if (query.getDescription() != null) {
      dept.setDescription(query.getDescription());
    }
    if (query.getSortOrder() != null) {
      dept.setSortOrder(query.getSortOrder());
    }
    if (query.getPhone() != null) {
      dept.setPhone(query.getPhone());
    }
    if (query.getEmail() != null) {
      dept.setEmail(query.getEmail());
    }
    if (query.getAddress() != null) {
      dept.setAddress(query.getAddress());
    }

    deptDao.save(dept);
  }

  public void delete(String id) {
    if (deptDao.countByParentId(id) > 0) {
      throw new BusinessException("部门下存在子部门，无法删除");
    }
    deptDao.deleteById(id);
  }

  public void deleteBatch(List<String> ids) {
    for (String id : ids) {
      delete(id);
    }
  }

  @Transactional(readOnly = true)
  public Optional<DeptEntity> getById(String id) {
    return deptDao.findById(id);
  }

  @Transactional(readOnly = true)
  public Optional<DeptEntity> getByCode(String deptCode) {
    return deptDao.findByDeptCode(deptCode);
  }

  @Transactional(readOnly = true)
  public List<DeptQueryVm.Result> queryPage(DeptQueryVm.Query query) {
    List<DeptEntity> depts = deptDao.findByStatusOrderBySortOrder(1);
    return depts.stream().map(this::toResult).collect(Collectors.toList());
  }

  @Transactional(readOnly = true)
  public List<DeptQueryVm.Result> queryTree() {
    List<DeptEntity> rootDepts = deptDao.findRootDepts();
    return rootDepts.stream()
        .map(dept -> buildTreeNode(dept, deptDao.findByParentIdOrderBySortOrder(dept.getId())))
        .collect(Collectors.toList());
  }

  @Transactional(readOnly = true)
  public List<DeptQueryVm.Result> queryChildren(String parentId) {
    List<DeptEntity> children = deptDao.findByParentIdOrderBySortOrder(parentId);
    return children.stream().map(this::toResult).collect(Collectors.toList());
  }

  public void enable(String id) {
    DeptEntity dept = deptDao.findById(id).orElseThrow(() -> new BusinessException("部门不存在"));
    dept.setStatus(1);
    deptDao.save(dept);
  }

  public void disable(String id) {
    DeptEntity dept = deptDao.findById(id).orElseThrow(() -> new BusinessException("部门不存在"));
    dept.setStatus(0);
    deptDao.save(dept);
  }

  @Transactional(readOnly = true)
  public void checkDeptCodeUnique(String deptCode, String excludeId) {
    Optional<DeptEntity> existing = deptDao.findByDeptCode(deptCode);
    if (existing.isPresent() && !existing.get().getId().equals(excludeId)) {
      throw new BusinessException("部门编码已存在");
    }
  }

  @Transactional(readOnly = true)
  public void checkParentIdValid(String parentId) {
    if (!deptDao.existsById(parentId)) {
      throw new BusinessException("父部门不存在");
    }
  }

  private DeptQueryVm.Result toResult(DeptEntity dept) {
    DeptQueryVm.Result result = new DeptQueryVm.Result();
    result.setId(dept.getId());
    result.setDeptCode(dept.getDeptCode());
    result.setDeptName(dept.getDeptName());
    result.setParentId(dept.getParentId());
    result.setLeaderId(dept.getLeaderId());
    result.setDescription(dept.getDescription());
    result.setSortOrder(dept.getSortOrder());
    result.setStatus(dept.getStatus());
    result.setPhone(dept.getPhone());
    result.setEmail(dept.getEmail());
    result.setAddress(dept.getAddress());
    result.setCreateTime(dept.getCreateTime());
    result.setUpdateTime(dept.getUpdateTime());
    return result;
  }

  private DeptQueryVm.Result buildTreeNode(DeptEntity dept, List<DeptEntity> children) {
    DeptQueryVm.Result result = toResult(dept);
    if (!children.isEmpty()) {
      result.setChildren(
          children.stream()
              .map(
                  child ->
                      buildTreeNode(child, deptDao.findByParentIdOrderBySortOrder(child.getId())))
              .collect(Collectors.toList()));
    }
    return result;
  }
}
